home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 147 / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin / games / ippon / source.lzh / enemy.c < prev    next >
C/C++ Source or Header  |  2000-07-07  |  6KB  |  271 lines

  1. /* enemy.c */
  2.  
  3. #include <stdio.h>
  4. #include <xsp2lib.h>
  5.  
  6. #include "main.h"
  7. #include "player.h"
  8. #include "enemy.h"
  9. #include "shot.h"
  10. #include "psearch.h"
  11.  
  12. #define ENEMY_MAX    32    /* 敵最大数 */
  13.  
  14. static ENEMY enemy[ENEMY_MAX];    /* ワーク */
  15. static ENEMY *enemy_top,    /* 使用中のワークのリスト */
  16.  *enemy_null_top,        /* 空のワークのリスト */
  17.  *enemy_end;            /* 使用中ワークのリストの末尾 */
  18.  
  19.  
  20.  
  21. /* 初期化関数へのポインタの配列 */
  22. typedef void (*enemy_alloc) (ENEMY *);
  23. enemy_alloc EnemyAllocFunc[] =
  24. {
  25.     EnemyAllocZakoA,
  26.     EnemyAllocZakoB,
  27.     EnemyAllocCoverN,
  28.     EnemyAllocOplaser,
  29.     EnemyAllocRound4,
  30.     EnemyAllocCoverF,
  31.     EnemyAllocSword,
  32.     EnemyAllocSearchZ,
  33.     EnemyAllocSearchZ2,
  34.     EnemyAllocZako031,
  35.     EnemyAllocLBoss01,
  36.     EnemyAllocLBoss01C,
  37. };
  38.  
  39. #define wabs(x) ((x) >= 0 ? (short) (x) : (short) -(x))
  40. #define abs(x)  ((x) >= 0 ? (int) (x) : (int) -(x))
  41.  
  42.  
  43.  /* ゲーム開始時に呼ばれる */
  44. void EnemyInit (void)
  45. {
  46.     int i;
  47.  
  48.     /* リストをつなげる */
  49.     enemy_top = NULL;
  50.     enemy_end = NULL;
  51.     enemy_null_top = enemy;
  52.     for (i = 0; i < ENEMY_MAX; i++)
  53.         enemy[i].next = &enemy[i + 1];
  54.  
  55.     enemy[ENEMY_MAX - 1].next = NULL;
  56. }
  57.  
  58.  
  59.  
  60. /* 敵出現時に呼ばれる */
  61. ENEMY *EnemyAlloc (short type, signed short x, signed short y)
  62. {
  63.     ENEMY *p;
  64.  
  65.     if (enemy_null_top == NULL)
  66.         return (NULL);    /* 空きのワークがない(キャラクターオーバー) */
  67.  
  68.     /* リストの末尾に新しいノードを追加(他とは違うので注意) */
  69.     p = enemy_null_top;
  70.     enemy_null_top = p->next;
  71.     if (enemy_top == NULL)
  72.         enemy_top = p;
  73.     else
  74.         enemy_end->next = p;
  75.     p->next = NULL;
  76.     enemy_end = p;
  77.  
  78.     p->type = type;
  79.     p->lx = x << 16;
  80.     p->ly = y << 16;
  81.     p->shot = NULL;
  82.  
  83.     /* 関数へのポインタを使って分岐 */
  84.     /* type が 0 なら EnemyAllocA() が、1 なら EnemyAllocB() が実行される */
  85.     EnemyAllocFunc[p->type] (p);
  86.  
  87.     return (p);
  88. }
  89.  
  90.  
  91.  
  92. /* 垂直同期ごとに呼ばれる */
  93. void EnemyMove (void)
  94. {
  95.     ENEMY *p, *q;
  96.     signed short pl_x = player->x, pl_y = player->y;
  97.  
  98. #ifdef DEBUG
  99.     enemy_sum = 0;
  100. #endif
  101.  
  102.     p = enemy_top;        /* 現在注目しているワーク */
  103.     q = NULL;        /* 1つ前のワーク(ワーク削除時に必要) */
  104.     while (p != NULL) {
  105.         /* 敵キャラの移動ルーチン */
  106.  
  107. #ifdef DEBUG
  108.         enemy_sum++;
  109. #endif
  110.  
  111.         /* 関数へのポインタを使って分岐 */
  112.         /* (FuncEnemy/ 以下の FuncMoveXXX() を呼んでいる) */
  113.         if ((p->func_enemy_move) (p)) {        /* 返り値が非0なら消去 */
  114.             (p->func_enemy_free) (p);    /* 消去関数を呼ぶ */
  115.             if (q == NULL) {    /* リストの一番最初を削除 */
  116.                 enemy_top = p->next;
  117.                 p->next = enemy_null_top;
  118.                 enemy_null_top = p;
  119.                 q = NULL;
  120.                 p = enemy_top;
  121.             } else {
  122.                 if (p == enemy_end) {    /* リストの一番最後を削除 */
  123.                     q->next = NULL;
  124.                     enemy_end = q;
  125.                     p->next = enemy_null_top;
  126.                     enemy_null_top = p;
  127.                     p = q->next;
  128.                 } else {
  129.                     q->next = p->next;
  130.                     p->next = enemy_null_top;
  131.                     enemy_null_top = p;
  132.                     p = q->next;
  133.                 }
  134.             }
  135.         } else {
  136.             /* 敵キャラを消去しない場合 */
  137.             SHOT *p2 = shot;    /* 現在注目しているショットのワーク */
  138.             signed short t;
  139.  
  140.             /* プレイヤーとの当たり判定 */
  141.             if (((t = p->x + p->hit_sx) > pl_x)
  142.                 && ((t -= (short) (p->hit_sx << 1)) < pl_x)
  143.                 && ((t = p->y + p->hit_sy) > pl_y)
  144.                 && ((t -= (short) (p->hit_sy << 1)) < pl_y)) {
  145.                 /* 当たった */
  146.                 if ((player->status == PLAYER_STATUS_ALIVE) && (player->muteki == 0))
  147.                     player->status = PLAYER_STATUS_DEAD;
  148.             }
  149.             /* ショットとの当たり判定 */
  150.             if (p2->status != SHOT_STATUS_NON) {
  151.                 signed short p2_w;
  152.                 short hit_w;
  153.                 if (((t = p->x + (hit_w = p->hit_sx)) >= (p2_w = *((short *) (&p2->lx))))
  154.                     && ((t -= (short) (hit_w << 1)) <= p2_w)
  155.                     && ((t = p->y + (hit_w = p->hit_sy)) >= (p2_w = *((short *) (&p2->ly))))
  156.                     && ((t -= (short) (hit_w << 1)) <= p2_w)) {
  157.  
  158.                     p->damage++;    /* 敵キャラにダメージを与える */
  159.                     /* ショットが当たった */
  160.                     if (p->damage_mode == DAMAGE_THROUGH) {
  161.                         /* ショットが貫通する敵の場合 */
  162.                         p->shot_count = p2->shot_count;
  163.                         if (p2->shot_count < 3)
  164.                             p2->shot_count++;
  165.                     } else {
  166.                         /* ショットが刺さる敵の場合 */
  167.                         if (p2->enemy == NULL) {
  168.                             /* 既に刺さっていなければ */
  169.                             if (p2->shot_count < 3)
  170.                                 p2->shot_count++;
  171.                             p2->status = SHOT_STATUS_STICK;
  172.                             p2->enemy = p;
  173.                             p2->off_x = p2->x - p->x;
  174.                             p2->off_y = p2->y - p->y;
  175.                             p->shot = p2;
  176.                         }
  177.                     }
  178.                 }
  179.             }
  180.             q = p;
  181.             p = p->next;
  182.         }
  183.     }
  184. }
  185.  
  186.  
  187.  
  188.  
  189. /* サービスルーチン */
  190.  
  191. enum {
  192.     MOVESEQ_ADD, MOVESEQ_FIX, MOVESEQ_SUB, MOVESEQ_END
  193. };
  194.  
  195. /* 絶対座標 dx,dy に向かって移動する(初期化) */
  196. void SubEnemyMoveToInit (ENEMY * p, signed short dest_x, signed short dest_y,
  197.              unsigned char speed, signed short count)
  198. {
  199.     unsigned char angle;
  200.     signed short sx, sy;
  201.  
  202.     sx = wabs (dest_x - p->x);
  203.     sy = wabs (dest_y - p->y);
  204.     angle = msearch (p->x, p->y, dest_x, dest_y);    /* 移動方向 */
  205.     p->move_ax = xytable[speed][angle].x / 32;
  206.     p->move_ay = xytable[speed][angle].y / 32;
  207.  
  208.     p->move_counter = p->move_count = count;    /* 何回加速/減速するか */
  209.  
  210.     /* 誤差を少なくするために大きい方で計算 */
  211.     /* 除数が絶対に 0 にならないようにするため +1 しています(小細工) */
  212.     if (sx > sy)
  213.         p->move_count2 = sx * 65536 / (abs (p->move_ax * count) + 1) - count;
  214.     else
  215.         p->move_count2 = sy * 65536 / (abs (p->move_ay * count) + 1) - count;
  216.  
  217.     p->move_count3 = 0;    /* 実際に加速/減速した回数 */
  218.     p->move_seq = MOVESEQ_ADD;
  219. }
  220.  
  221.  
  222.  
  223. /* 座標 dx,dy に向かって移動する */
  224. short SubEnemyMoveTo (ENEMY * p)
  225. {
  226.     switch (p->move_seq) {
  227.     case MOVESEQ_ADD:    /* 加速中 */
  228.         p->vx += p->move_ax;
  229.         p->vy += p->move_ay;
  230.         p->move_count3++;
  231.         if (p->move_counter-- <= 0) {
  232.             p->move_seq++;    /* 加速したら次へ */
  233.             p->move_counter = p->move_count2;
  234.         }
  235.         break;
  236.     case MOVESEQ_FIX:    /* 等速度運動中 */
  237.         if (p->move_counter-- <= 0) {
  238.             p->move_seq++;    /* 加速したら次へ */
  239.             p->move_counter = p->move_count;
  240.         }
  241.         break;
  242.     case MOVESEQ_SUB:    /* 減速中 */
  243.         p->vx -= p->move_ax;
  244.         p->vy -= p->move_ay;
  245.         p->move_count3--;
  246.         if (p->move_counter-- <= 0)    /* ある程度減速したら次へ */
  247.             p->move_seq++;
  248.         break;
  249.     case MOVESEQ_END:
  250.         p->vx = p->vy = p->move_ax = p->move_ay = 0;
  251.         return (-1);
  252.     }
  253.     return (0);
  254. }
  255.  
  256.  
  257.  
  258. /* 移動を中断する */
  259. short SubEnemyMoveToAbort (ENEMY * p)
  260. {
  261.     if (p->move_count3-- <= 0) {
  262.         p->vx = 0;
  263.         p->vy = 0;
  264.         return (-1);
  265.     }
  266.     p->vx -= p->move_ax;
  267.     p->vy -= p->move_ay;
  268.  
  269.     return (0);
  270. }
  271.